package kai.rating;

import java.util.Random;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.content.SharedPreferences;

public class Elo
{
	private static SQLiteDatabase db;
	private static SharedPreferences pref;
	
	private static int Kfactor; //bigger:match with big point (total match point)
	private static int diff; //1:chance is always 0.5,bigger:more bent for chance curve
	private static int block; //bigger:easy to escape from average
	private static boolean debug;
	
	protected static int left,right=-1; //fighter's position
	private static double elo_l,elo_r=0;
	private static int win_l,win_r,draw=0;
	protected static EloObject[] object;
	protected static int row;
	
	protected Elo(Context c,SharedPreferences _pref)
	{
		db=new DBHelper(c).getWritableDatabase();
		pref=_pref;
		if(row<0)
			return;
	}

	protected static void Refresh()
	{
		Kfactor=pref.getInt("Kfactor",100);
		diff=pref.getInt("diff",10);
		block=pref.getInt("block",400);
		debug=pref.getBoolean("debug",false);

		row=DBHelper.GetRows(db);
		object=new EloObject[row];
		for(int i=0;i<row;i++)
			object[i]=new EloObject();
		DBHelper.GetObjs(db, object,null);
	}
	
	protected static int GetNum()
	{
		return row;
	}
	
	protected static int GetId(int rowid)
	{
		return object[rowid].id;
	}
	protected static String GetName(int rowid)
	{
		return object[rowid].name;
	}
	protected static int GetPoint(int rowid)
	{
		return object[rowid].point;
	}
	protected static void calc()
	{
		double Qa=Math.pow(diff,(double)object[left].point/(block));
		double Qb=Math.pow(diff,(double)object[right].point/(block));
		elo_l=Qa/(Qa+Qb);
		elo_r=Qb/(Qa+Qb);
		win_l=(int) (Kfactor*(1-elo_l));
		win_r=(int) (Kfactor*(1-elo_r));
		draw=(win_l-win_r)/2;
	}
	protected static boolean Fight()
	{
		if(row<2)
			return false;
		Random rand=new Random();
		left=rand.nextInt(row);
		right=(left+1+rand.nextInt(row-1))%row;
		calc();
		return true;
	}
	protected static boolean Win(int win)
	{
		boolean r0,r1;
		switch(win)
		{
		case 0:
			r0=DBHelper.SetPoint(db,object[left].id,object[left].point+draw);
			r1=DBHelper.SetPoint(db,object[right].id,object[right].point-draw);
			break;
		case 1:
			r0=DBHelper.SetPoint(db,object[left].id,object[left].point+win_l);
			r1=DBHelper.SetPoint(db,object[right].id,object[right].point-win_l);
			break;
		case 2:
			r0=DBHelper.SetPoint(db,object[left].id,object[left].point-win_r);
			r1=DBHelper.SetPoint(db,object[right].id,object[right].point+win_r);
			break;
		default:
			r0=r1=false;
		}
		Refresh();
		return r0&&r1;
	}

	protected static String Print()
	{
		StringBuffer prn=new StringBuffer();
		if(row>=2)
		{
			if(debug)
			{
				prn.append("Options:");
				prn.append("\nKfactor:"+Kfactor);
				prn.append("\ndiff:"+diff);
				prn.append("\nblock:"+block);
				prn.append("\n\n");
				prn.append(object[left].name+"("+object[left].point+")"+": vs :"+object[right].name+"("+object[right].point+")");
				prn.append("\n"+elo_l+": Odds :"+elo_r);
				prn.append("\n"+object[left].point+"+"+win_l+"=>"+(object[left].point+win_l)+": Win :"+object[right].point+"+"+win_r+"=>"+(object[right].point+win_r));
				prn.append("\n"+object[left].point+"-"+win_r+"=>"+(object[left].point-win_r)+": Lose :"+object[right].point+"-"+win_r+"=>"+(object[right].point-win_l));
				prn.append("\n"+object[left].point+(draw>=0?"+":"")+draw+"=>"+(object[left].point+draw)+" Draw "+object[right].point+(draw<=0?"+":"")+-draw+"=>"+(object[right].point-draw));
			}
			else
			{
				prn.append(object[left].point+": Point :"+object[right].point);
				prn.append("\n"+Math.round(elo_l*1000)+": Odds :"+Math.round(elo_r*1000));
			}
		}
		return prn.toString();
	}
}

class EloObject
{
	protected int id;
	protected String name;
	protected int point;
	protected EloObject()
	{
		id=-1;
		name="Null";
		point=0;
	}
}